package com.example;

import java.io.Serializable;
import java.util.Stack;


// 修改 ChessBoard 实现自定义主题接口
public class ChessBoard implements ChessSubject {
    private final int[][] grid;     // 棋盘 0-空，1-黑棋，2-白棋
    private final int size;         // 棋盘尺寸
    private int player;             // 玩家 1, 2
    private final Stack<Move> history = new Stack<>(); // 历史记录栈
    private java.util.List<ChessObserver> observers = new java.util.ArrayList<>();

    // 内部类：记录每一步落子信息（坐标和玩家）
    public static class Move implements Serializable {
        int x, y, player;
        Move(int x, int y, int player) {
            this.x = x;
            this.y = y;
            this.player = player;
        }
    }

    public ChessBoard(int size) {
        this.size = size;
        grid = new int[size][size];
        this.player = 1;
    }

    // 玩家落子
    public void placeChess(int x, int y){
        grid[x][y] = player;
        history.push(new Move(x, y, player));   // 保存当前玩家（落子后还未切换）
        System.out.println("Player " + player + " placed at (" + x + ", " + y + ")");
        player = player == 1 ? 2 : 1;           // 切换玩家
        notifyObservers();
    }

    // 撤销上一步
    public boolean undoMove() {
        if (history.isEmpty())
            return false;
        Move lastMove = history.pop();
        grid[lastMove.x][lastMove.y] = 0;     // 清除棋子
        player = lastMove.player;      // 恢复玩家
        return true;
    }

    // 胜负判断
    public boolean isGameOver(int x, int y){
        /* 以当前落子为起点，检查四个方向是否达成5子连续 */
        int player = grid[x][y];
        int[][] directions = {{1,0}, {0,1}, {1,1}, {1,-1}}; // 水平、垂直、对角线、反斜线
        for (int[] dir : directions) {
            int count = 1;
            // 正向检查
            int dx = x + dir[0], dy = y + dir[1];
            while (dx >= 0 && dx < size && dy >= 0 && dy < size && grid[dx][dy] == player) {
                count++;
                dx += dir[0];
                dy += dir[1];
            }
            // 反向检查
            dx = x - dir[0];
            dy = y - dir[1];
            while (dx >= 0 && dx < size && dy >= 0 && dy < size && grid[dx][dy] == player) {
                count++;
                dx -= dir[0];
                dy -= dir[1];
            }
            if (count >= 5)
                return true; // 五子连珠
        }
        return false;
    }

    public int getSize() {
        return size;
    }


    public int[][] getGrid() {
        return grid;
    }

    public int getCurrentPlayer(){
        return player;
    }

    public void reset(){
        for (int x = 0; x < size; x++){
            for (int y = 0; y < size; y++){
                grid[x][y] = 0;
            }
        }
        history.clear();
        player = 1;
    }

    // 获取历史记录栈
    public Stack<Move> getHistory() {
        return history;
    }

    // 设置棋盘状态
    public void setGrid(int[][] grid) {
        for (int i = 0; i < size; i++) {
            System.arraycopy(grid[i], 0, this.grid[i], 0, size);
        }
    }

    // 设置历史记录栈
    public void setHistory(Stack<Move> history) {
        this.history.clear();
        this.history.addAll(history);
    }

    // 设置当前玩家
    public void setCurrentPlayer(int player) {
        this.player = player;
    }

    @Override
    public void addObserver(ChessObserver observer) {
        observers.add(observer);
    }

    @Override
    public void removeObserver(ChessObserver observer) {
        observers.remove(observer);
    }

    @Override
    public void notifyObservers() {
        Move lastMove = history.peek();
        boolean GameOver = isGameOver(lastMove.x, lastMove.y);
        // 通知所有观察者更新棋盘状态
        for (ChessObserver observer : observers) {
            observer.updateBoard(getGrid(), lastMove.x, lastMove.y, lastMove.player, GameOver);
        }
    }
}